package processes.jurassicPark;

import java.util.Random;
import os.MiniMutex;
import os.MiniSemaphore;
import os.MiniThread;

public class CarStock
{
	private int passngerNum, carsNum, ridingMin, ridingMax;
	private boolean carAvailable[];
	private int passengerCar[];
	private MiniMutex canSelectCar;
	private MiniSemaphore carsAvailableNum;
	private MiniMutex carTaken[];
	private MiniMutex carRelease[];
	
	public CarStock(int passengerNum, int carsNum, int ridingMin, int ridingMax)
	{
		this.passngerNum = passengerNum;
		this.carsNum = carsNum;
		this.ridingMin = ridingMin;
		this.ridingMax = ridingMax;
		carAvailable = new boolean[carsNum];
		passengerCar = new int[passengerNum];
		canSelectCar = new MiniMutex(1);
		carsAvailableNum = new MiniSemaphore(0);
		carTaken = new MiniMutex[carsNum];
		carRelease = new MiniMutex[carsNum];
		for(int i = 0; i < carsNum; i++)
		{
			carTaken[i] = new MiniMutex(0);
			carRelease[i] = new MiniMutex(0);
			carAvailable[i] = false;
		}
	}
	
	public void takeACar(int passengerNum, MiniThread passengerThread)
	{
		System.err.println("Passenger no "+passengerNum+" try to take a car");
//		int j = 0;
		passengerThread.isExcecutionStopped();
		carsAvailableNum.P();
		System.err.println("Passenger no "+passengerNum+" wait to select a car");
		passengerThread.isExcecutionStopped();
		canSelectCar.P();
		passengerThread.isExcecutionStopped();
			for(int i = 0; i < carsNum; i++)
			{
				passengerThread.isExcecutionStopped();
				if(carAvailable[i])
				{
					passengerThread.isExcecutionStopped();
					System.err.println("Passenger no "+passengerNum+" take car no"+i);
					carAvailable[i] = false;
					passengerCar[passengerNum] = i;
					break;
				}
			}
			passengerThread.isExcecutionStopped();
//			System.out.println("Passenger no "+passengerNum+" signal selecting a car");
		canSelectCar.V();
		passengerThread.isExcecutionStopped();
		carTaken[passengerCar[passengerNum]].V();
		passengerThread.isExcecutionStopped();
		System.err.println("Passenger no "+passengerNum+" will wait for a tour to finish");
		carRelease[passengerCar[passengerNum]].P();
		passengerThread.isExcecutionStopped();
//		System.err.println("Passenger no "+passengerNum+" finished");
	}
	
	public void carArrived(int carNum, MiniThread carThread)
	{
		while(true)
		{
			System.err.println("Car no "+carNum+" is now available");
			carThread.isExcecutionStopped();
			carAvailable[carNum] = true;
			carsAvailableNum.V();
			carThread.isExcecutionStopped();
//			System.out.println("Car no "+carNum+" is now waiting a passenger");
			carTaken[carNum].P();
			try
			{
				carThread.isExcecutionStopped();
				System.err.println("Car no "+carNum+" take passenger");
				Random random = new Random();
				int intervalTime = random.nextInt(ridingMax - ridingMin);
				carThread.isExcecutionStopped();
				intervalTime += ridingMin;
				carThread.isExcecutionStopped();
				Thread.sleep(intervalTime);
				carThread.isExcecutionStopped();
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			carThread.isExcecutionStopped();
			carRelease[carNum].V();
			carThread.isExcecutionStopped();
//			System.out.println("Car no "+carNum+" is now released");
		}
	}
}
